

#include "thread_open.h"

#include <QTimer>
#include <QTime>
#include <QDebug>
#include <qdatetime.h>

#include <iostream>
#include <fstream>

using namespace std;

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <getopt.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include <malloc.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/mman.h>
#include <sys/ioctl.h>

#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>




#include <asm/types.h>
#include "global.h"

//#include "/home/yu/QTworkspace/VDMA.c"

QTime start_time;
QTime end_time;

QTime start_time0;
QTime end_time0;

int rx_temp=0;
// debug params
short in_802816[802816]={0};
int debug=0;
int readstate_open = 1 - debug;
// end debug
CvCapture *to_pCapture = NULL;
IplImage *to_pFrame = NULL, *to_srcImage=NULL;
IplImage *to_img_out_1 =cvCreateImage(cvSize(640,480),IPL_DEPTH_8U,3);
IplImage *to_img_out_2 =cvCreateImage(cvSize(640,480),IPL_DEPTH_8U,4);
IplImage *to_img_out_3 =cvCreateImage(cvSize(960,720),IPL_DEPTH_8U,4);
IplImage *to_img_out_1920_1080_3 =cvCreateImage(cvSize(1920,1080),IPL_DEPTH_8U,3);
IplImage *to_img_out_1920_1080_4 =cvCreateImage(cvSize(1920,1080),IPL_DEPTH_8U,4);
char rtsp_out_file_name[100] = "/home/linaro/rtspimg/";
int rtsp__out_index=0;
cv::Mat frame;
//cv::VideoCapture cap(RTSP_ADDRESS);
cv::Mat dst(720, 960, CV_8UC3);
cv::Mat dst2(448, 448, CV_8UC3);
cv::Mat dst3(448, 448, CV_8UC4,cvScalar(0,0,0,0));

char socket_buf[SOCKET_BUFF_SIZE];
int run_times = 0;
int socketfd = socket(AF_INET, SOCK_STREAM, 0);
struct sockaddr_in addr;
int use_socket = 0;
int socket_init = 0;
int socket_ret;
int nNetTimeout = 10000; //10秒
int remain_size = SOCKET_BUFF_SIZE;
int recv_size = 0;
int need_recv_size = 0;
int file_name_length = 0;
FILE * image_pFile;
char socket_start_flag[6] = "START";
void socket_get(int shownum){
    qDebug() << "SOCKET get img";
    try{
        if(run_times>10){
            run_times = 0;
        }
        run_times ++;
        if(socket_ret != -1){
            qDebug() << "socket get image";
//            remain_size = SOCKET_BUFF_SIZE;
//            while(remain_size>0){
//                recv_size = recv(socketfd, socket_buf + SOCKET_BUFF_SIZE - remain_size, remain_size,0);
//                remain_size -= recv_size;
//                qDebug() << "remain_size"<< remain_size<< "recv_size"<< recv_size;
//            }
            int match_num = 0;
            while(match_num<5){
                recv_size = recv(socketfd, socket_buf, 1,MSG_WAITALL);
                if(recv_size<1){
                    // socket cut off
                    socket_connect();
                    return;
                }
                if(socket_buf[0] == socket_start_flag[match_num]){
                    match_num ++;
                }else{
                    match_num = 0;
                }
            }
            recv_size = recv(socketfd, &need_recv_size, 4,MSG_WAITALL);
            qDebug() << "recv_size"<< recv_size<< "need_recv_size"<< need_recv_size;
            if (need_recv_size < 0 || need_recv_size > 108 + 2073600)return;
            recv_size = recv(socketfd, socket_buf, need_recv_size-4,MSG_WAITALL);
            qDebug() << "recv_size"<< recv_size;

            if(socket_buf[0] == 'A'){
                file_name_length = *(socket_buf+4);
                memcpy(rtsp_out_file_name+21, socket_buf+8,file_name_length);
                msync(socket_buf+8, file_name_length, MS_SYNC);
                if (FILE *file = fopen(rtsp_out_file_name, "r")) {
                    fclose(file);
                } else {
                    ofstream outfile(rtsp_out_file_name,ios::out|ios::binary);
                    outfile.write(socket_buf+104, need_recv_size-108);
                    outfile.close();
                }
            }else if(socket_buf[0] == 'D'){
                memcpy(IM_show[shownum].data, socket_buf+104,SOCKET_BUFF_SIZE-1);
                msync((IM_show[shownum].data), SOCKET_BUFF_SIZE-1, MS_SYNC);
            }else if(socket_buf[0] == 'S'){
                memcpy(IM_show[shownum].data, socket_buf+104,SOCKET_BUFF_SIZE-1);
                msync((IM_show[shownum].data), SOCKET_BUFF_SIZE-1, MS_SYNC);
                cv::imwrite(rtsp_out_file_name, IM_show[shownum]);
            }else{
                qDebug() << "error label" << socket_buf[0];
            }



//            qDebug() << "display frame";
//            memcpy(IM_show[shownum].data, socket_buf+1,SOCKET_BUFF_SIZE-1);
//            msync((IM_show[shownum].data), SOCKET_BUFF_SIZE-1, MS_SYNC);
//            qDebug() << "IM_show"<<shownum<<"get";
//            if(socket_buf[0]=='1'){
//                qDebug() << "save frame";
//                rtsp__out_index += 1;
//                sprintf(rtsp_out_file_name, "/home/linaro/rtspimg/orisleep4%d.jpg", rtsp__out_index);
//                qDebug() << "save frame" << rtsp_out_file_name;
//                cv::imwrite(rtsp_out_file_name, IM_show[shownum]);
//                if(rtsp__out_index%10==0){
//                    socket_connect();
//                }
//            }else{
//                qDebug() << "no display frame";
//            }

        }else{
            qDebug() << "socket closed";
            socket_connect();
        }
        return;
    }catch (...) {
        qDebug() << "socket read error";
    }

}

void camera_get(int shownum)
{

    if(USE_CAMERA)ioctl(fd, VIDIOC_DQBUF, &buf);

    // Process the frame
    QTime start_timerd;
    start_timerd = QTime::currentTime();

    //cvSetData(iplImage,framebuf[buf.index].start,VIDEO_WIDTH*2);
    //qDebug() << "buf.index"<< (int)buf.index;
    memcpy(fbaddr0[buf.index].fbV, framebuf[buf.index].start, VIDEO_WIDTH*VIDEO_HEIGHT*2*sizeof(char));
    // copy from framebuf to fbaddr0


    QTime end_timewr;
    end_timewr = QTime::currentTime();

    //qDebug() << "vdma_start_buffering";
    //    struct timeval timeout;
    //    timeout.tv_sec = SOCKET_READ_TIMEOUT_SEC;
    //    timeout.tv_usec = 0;
    //    setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout));
    vdma_start_buffering_set(&vdma0, VDMA_WRITE);
    //qDebug() << "vdma_start_0";
    vdma_start_buffering_set(&vdma1, VDMA_READ);
    //qDebug() << "vdma_start_1";
    vdma_start_buffering_set(&vdma2, VDMA_READ);
    //qDebug() << "vdma_start_2";

    msync((framecontrol[0].start), 24*sizeof(int), MS_SYNC);

    //qDebug() << "msync";

    framecontrol[0].RS = (framecontrol[0].start)[0];
    //framecontrol[0].RS = 1;

    framecontrol[0].WK_ID = tx_id;
    (framecontrol[0].start)[5] = framecontrol[0].WK_ID;

    framecontrol[0].lOCK_STATE = (framecontrol[0].start)[3];

    framecontrol[0].RX_ID = (framecontrol[0].start)[6];

    if(framecontrol[0].lOCK_STATE == 0){
        framecontrol[0].TX_ID = (framecontrol[0].start)[4];
        tx_id = framecontrol[0].TX_ID;

        framecontrol[0].lOCK_STATE = 1;
        //framecontrol[0].RX_ID = (framecontrol[0].start)[6];
        framecontrol[0].MREADY == (framecontrol[0].start)[15];

        (framecontrol[0].start)[3] = framecontrol[0].lOCK_STATE;
        //qDebug()<<"lock-state done";
    }
    else{
        //qDebug()<<"lock-state pass";
    }

    if(rx_temp != framecontrol[0].RX_ID){

        rx_temp = framecontrol[0].RX_ID;
        end_time0 = QTime::currentTime();

        int tt;
        tt = start_time0.msecsTo(end_time0);
        qDebug() << "chip compute time: "<< tt;
        start_time0 = QTime::currentTime();
    }


    tx_id = loop_id(tx_id);
    if(framecontrol[0].TX_ID == tx_id){
        tx_id = loop_id(tx_id);
    }

    //qDebug() << "TX_ID"<< framecontrol[0].TX_ID;


    vdma_start_buffering(&vdma2, fbaddr2, tx_id, VDMA_READ);
    vdma_start_buffering(&vdma1, fbaddr1, (int)buf.index, VDMA_READ);

    //qDebug()<<"vdma_start_buffering";

    while(1!=vdma_running(&vdma1, 1)){qDebug() << "vdma1_IsNotReady";usleep(100);}


    XCvt_resize_Start(&Cvt_resize);

    //qDebug()<<"XCvt_resize_Start";


    vdma_start_buffering(&vdma0, fbaddr0, (int)buf.index, VDMA_WRITE);




    while(0!=XCvt_resize_IsReady(&Cvt_resize)){qDebug() << "XCvt_resize_IsNotReady";usleep(100);}


    while(0==XCvt_resize_IsDone(&Cvt_resize))
    {
        usleep(100);
        //qDebug()<<"wait XCvt_resize_IsDone";
    }



    while(0!=vdma_running(&vdma1, 1)){
        //qDebug() << "vdma1_IsNotDone";
        usleep(100);
    }
    if(!RTSP){
//        cvSetData(IM_show[shownum],fbaddr1[buf.index].fbV,960*4);
    }
    if(!RTSP){
        qDebug() << "RTSP get img";
        try{
            if(run_times>10){
                run_times = 0;
            }
            run_times ++;
            if(socket_ret != -1){
                qDebug() << "socket get image";
//                socket_buf[0] = '1';
//                send(socketfd, socket_buf, 1, 0);
//                usleep(10000);
                int remain_size = SOCKET_BUFF_SIZE;
                while(remain_size>0){
                    int recv_size = recv(socketfd, socket_buf + SOCKET_BUFF_SIZE - remain_size, remain_size,0);
                    remain_size -= recv_size;
//                    qDebug() << "remain_size"<< remain_size<< "recv_size"<< recv_size;
                }

                qDebug() << "display frame";
//                cv::Mat dst(720, 960, CV_8UC3);
                memcpy(IM_show[shownum].data, socket_buf+1,SOCKET_BUFF_SIZE-1);
                msync((IM_show[shownum].data), SOCKET_BUFF_SIZE-1, MS_SYNC);
                if(socket_buf[0]=='1'){
                    rtsp__out_index += 1;
                    sprintf(rtsp_out_file_name, "/home/linaro/rtspimg/orisleep4%d.jpg", rtsp__out_index);
                    qDebug() << "save frame" << rtsp_out_file_name;
                    cv::imwrite(rtsp_out_file_name, IM_show[shownum]);
                    if(rtsp__out_index%10==0){
                        int ret = shutdown(socketfd,SHUT_RDWR);
                        if(ret==0){
                            qDebug() << "close socket success";
                        }else{
                            qDebug() << "close socket fail";
                        }
                        socket_connect();
                    }
                }else{

                }
//                IM_show[shownum] = dst;

            }else{
                qDebug() << "socket closed";
                int ret = shutdown(socketfd,SHUT_RDWR);
                if(ret==0){
                    qDebug() << "shutdown socket success";
                }else{
                    qDebug() << "shutdown socket fail";
                }
                ret = close(socketfd);
                if(ret==0){
                    qDebug() << "close socket success";
                }else{
                    qDebug() << "close socket fail";
                }
                socket_connect();
            }
            return;


            cv::VideoCapture cap(RTSP_ADDRESS);
            if(!cap.isOpened()){
                cv::VideoCapture cap(RTSP_ADDRESS);
            }
            cap>>frame;
            if(frame.rows<1080||frame.cols<1920){
                qDebug() << "frame.rows<1080||frame.cols<1920";
            }
            qDebug() << "rows:"<<frame.rows<<"cols"<<frame.cols;
            if(frame.empty() || !cap.isOpened()){

            }else{
                rtsp__out_index += 1;
//                sprintf(rtsp_out_file_name, "/home/linaro/rtspimg/orisleep4%d.jpg", rtsp__out_index);
//                cv::imwrite(rtsp_out_file_name, frame);
//                qDebug() << rtsp_out_file_name;
//                sleep(4);

//                cv::Mat dst(960, 720, CV_8UC3);
//                cv::Mat dst2(960, 720, CV_8UC4);

                qDebug() << "mat";
                qDebug() << "iplimg";
                cv::resize(frame, dst, cv::Size(960, 720), cv::INTER_NEAREST);
                cv::resize(dst, dst2, cv::Size(448, 448), cv::INTER_NEAREST);
                cv::cvtColor(dst,dst,cv::COLOR_BGR2RGB);
//                sprintf(rtsp_out_file_name, "/home/linaro/rtspimg/resize%d.jpg", rtsp__out_index);
//                cv::imwrite(rtsp_out_file_name, dst);
                qDebug() << "resize";
                cv::cvtColor(dst2,dst3,cv::COLOR_BGR2BGRA);
                qDebug() << "rows:"<<dst3.rows<<"cols"<<dst3.cols;
                qDebug() << "TYPE:"<<dst3.type()<<"802816*sizeof(short)"<<802816*sizeof(short);
                for(int i=0;i<802816;i++){
                    in_802816[i] = (short)(*(dst3.data+i));
                }
                qDebug() << "memcpy";
                memcpy(fbaddr2[tx_id].fbV, in_802816,802816*sizeof(short));
                qDebug() << "msync";
                msync((fbaddr2[tx_id].fbV), 802816*sizeof(short), MS_SYNC);
//                sprintf(rtsp_out_file_name, "/home/linaro/rtspimg/input_img%d.dat", rtsp__out_index);
//                qDebug() << rtsp_out_file_name;
//                ofstream outFile(rtsp_out_file_name, ios::out | ios::binary);
//                outFile.write((char*)fbaddr2[tx_id].fbV, 802816*sizeof(short));
//                outFile.close();
                qDebug() << "end write img to dat";
                qDebug() << "cvtColor";
                IM_show[shownum] = dst;
//                *to_img_out_3 = IplImage(dst2);
//                qDebug() << dst2.step.p[0];
//                sprintf(rtsp_out_file_name, "/home/linaro/rtspimg/cvtColor%d.jpg", rtsp__out_index);
//                cv::imwrite(rtsp_out_file_name, dst2);
//                cvSetData(IM_show[shownum],dst2.data,960*4);
//                cvSetData(IM_show[shownum],to_img_out_3->imageData,960*4);
                qDebug() << "cvSetData";
            }

            cap.release();

            return;
        }
        catch (...) {
            qDebug() << "test socket read error";
        }

}


    if(RTSP){
        try{
            cv::VideoCapture cap(RTSP_ADDRESS);
            if(!cap.isOpened()){
                cv::VideoCapture cap(RTSP_ADDRESS);
            }
            cap>>frame;
            if(frame.rows<1080||frame.cols<1920){
                qDebug() << "frame.rows<1080||frame.cols<1920";
            }
            qDebug() << "rows:"<<frame.rows<<"cols"<<frame.cols;
            if(frame.empty() || !cap.isOpened()){

            }else{
                rtsp__out_index += 1;
//                sprintf(rtsp_out_file_name, "/home/linaro/rtspimg/orisleep4%d.jpg", rtsp__out_index);
//                cv::imwrite(rtsp_out_file_name, frame);
//                qDebug() << rtsp_out_file_name;
//                sleep(4);

//                cv::Mat dst(960, 720, CV_8UC3);
//                cv::Mat dst2(960, 720, CV_8UC4);

                qDebug() << "mat";
                qDebug() << "iplimg";
                cv::resize(frame, dst, cv::Size(960, 720), cv::INTER_NEAREST);
                cv::resize(dst, dst2, cv::Size(448, 448), cv::INTER_NEAREST);
                cv::cvtColor(dst,dst,cv::COLOR_BGR2RGB);
//                sprintf(rtsp_out_file_name, "/home/linaro/rtspimg/resize%d.jpg", rtsp__out_index);
//                cv::imwrite(rtsp_out_file_name, dst);
                qDebug() << "resize";
                cv::cvtColor(dst2,dst3,cv::COLOR_BGR2BGRA);
                qDebug() << "rows:"<<dst3.rows<<"cols"<<dst3.cols;
                qDebug() << "TYPE:"<<dst3.type()<<"802816*sizeof(short)"<<802816*sizeof(short);
                for(int i=0;i<802816;i++){
                    in_802816[i] = (short)(*(dst3.data+i));
                }
                qDebug() << "memcpy";
                memcpy(fbaddr2[tx_id].fbV, in_802816,802816*sizeof(short));
                qDebug() << "msync";
                msync((fbaddr2[tx_id].fbV), 802816*sizeof(short), MS_SYNC);
//                sprintf(rtsp_out_file_name, "/home/linaro/rtspimg/input_img%d.dat", rtsp__out_index);
//                qDebug() << rtsp_out_file_name;
//                ofstream outFile(rtsp_out_file_name, ios::out | ios::binary);
//                outFile.write((char*)fbaddr2[tx_id].fbV, 802816*sizeof(short));
//                outFile.close();
                qDebug() << "end write img to dat";
                qDebug() << "cvtColor";
                IM_show[shownum] = dst;
//                *to_img_out_3 = IplImage(dst2);
//                qDebug() << dst2.step.p[0];
//                sprintf(rtsp_out_file_name, "/home/linaro/rtspimg/cvtColor%d.jpg", rtsp__out_index);
//                cv::imwrite(rtsp_out_file_name, dst2);
//                cvSetData(IM_show[shownum],dst2.data,960*4);
//                cvSetData(IM_show[shownum],to_img_out_3->imageData,960*4);
                qDebug() << "cvSetData";
            }

            cap.release();

        }
        catch (...) {
            qDebug() << "test rtsp read error";
            try {
                cvReleaseCapture(&to_pCapture);
            } catch (...) {
                qDebug() << "to_pCapture release error";
            }
            to_pCapture =cvCreateFileCapture("rtsp://admin:y1997212@172.16.6.42/Streaming/Channels/1");
            cv::VideoCapture cap("rtsp://admin:y1997212@172.16.6.42/Streaming/Channels/1");
        }
    }

    else if(debug){
        memcpy(fbaddr2[tx_id].fbV, in_802816,802816*sizeof(short));
        msync((fbaddr2[tx_id].fbV), 802816*sizeof(short), MS_SYNC);
    }/*else{
        qDebug() << "start write img to dat";
        ofstream outFile("input_img.dat", ios::out | ios::binary);
        outFile.write((char*)fbaddr2[tx_id].fbV, 802816*sizeof(short));
        outFile.close();
        qDebug() << "end write img to dat";
    }*/
    // Re-queen buffer

    if(USE_CAMERA)ioctl(fd, VIDIOC_QBUF, &buf);

}

Thread_O::Thread_O()
{

}

void socket_connect(){
    int ret = shutdown(socketfd,SHUT_RDWR);
    if(ret==0){
        qDebug() << "shutdown socket success";
    }else{
        qDebug() << "shutdown socket fail";
    }
    ret = close(socketfd);
    if(ret==0){
        qDebug() << "close socket success";
    }else{
        qDebug() << "close socket fail";
    }
//    free(&socketfd);
    socketfd = socket(AF_INET, SOCK_STREAM, 0);
    socket_ret = connect(socketfd, (struct sockaddr*)(&addr), sizeof(struct sockaddr));
    if(socket_ret<0){
        qDebug()<<"socket_connect fail"<<socket_ret;
    }else{
        qDebug()<<"socket_connect success"<<socket_ret;
    }
//    struct timeval timeout;
//    timeout.tv_sec = SOCKET_READ_TIMEOUT_SEC;
//    timeout.tv_usec = 0;
//    setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout));
}

void Thread_O::run()
{

    msync((framecontrol[0].start), 24*sizeof(int), MS_SYNC);
    if(!socket_init && !RTSP){
        bzero(&addr, sizeof(struct sockaddr));
        addr.sin_family = AF_INET;
        addr.sin_port = htons(8001);
//        addr.sin_addr.s_addr = htonl(INADDR_ANY);
//        addr.sin_addr.s_addr =inet_addr("172.16.6.110");
        addr.sin_addr.s_addr =inet_addr("172.16.6.163");
//        addr.sin_addr.s_addr =inet_addr("172.16.6.110");
        socket_connect();
        socket_init = 1;
    }


        //debug mode
//    qDebug() << "int size" << sizeof(test_int);
//    exit(0);
        //readstate=1;
        //(framecontrol[0].start)[0] = 1;
        //

        //framecontrol[0].RS = (framecontrol[0].start)[0];

        if(readstate_open==0){

            if(RTSP){
                to_pCapture =cvCreateFileCapture("rtsp://admin:y1997212@172.16.6.42/Streaming/Channels/1");
            }
            //thread.start();

            readstate_open=1;


            //qDebug()<<"transfer complete";

            unsigned int temp;
            int k = 0;
            const char* ch = "/home/linaro/conv9.txt";
            /*
            ifstream file_name(ch);
            if (!file_name.is_open())
            {
                qDebug() << "open file error!";
            }


            while (!file_name.eof())
            {
                file_name>>hex>>temp;
                back_25088[k] = (short)temp;

                if(k<2){
                    qDebug()<<temp;
                }
                k++;

            }
            qDebug()<<k;
            file_name.close();
            */

            ch = "/home/linaro/conv0.txt";

            ifstream file_name2(ch);
            if (!file_name2.is_open())
            {
                qDebug() << "open file error!";
            }


            k = 0;

            while (!file_name2.eof())
            {
                file_name2>>hex>>temp;
                in_802816[k] = (short)temp;

                if(k<2){
                    qDebug()<<temp;
                }
                k++;

            }
            qDebug()<<k;
            file_name2.close();

        }


    int shotp = loop_id(shownum_temp);
    //qDebug()<<"getdata: "<< shotp;
    if(!RTSP){
        socket_get(shotp);
    }else{
        camera_get(shotp);
    }
    //camera_get(shownum_temp);
    shownum_temp = shotp;
    end_time = QTime::currentTime();

    int tt;
    tt = start_time.msecsTo(end_time);

    //int tt2;
    //tt2 = start_time_t.msecsTo(end_time);

    start_time = QTime::currentTime();

    qDebug() << "display time: " << tt;
    //qDebug() << "display time2: " << tt2;

    //qDebug() << "start_time:" << start_time_t.msec();
    //qDebug() << "end_time:" << end_time.msec();

}
